package edu.udlap.spring2008.is300.finalexam.app.mvc.view;

import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.database.objects.CategoryRecord;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.database.objects.FormatRecord;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.database.objects.ImageRecord;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.ModelState;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.database.objects.PrivacyLevelRecord;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.model.database.objects.SizeRecord;
import edu.udlap.spring2008.is300.finalexam.framework.mvc.view.ViewComponent;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;

    
/**
 *
 * @author Ruslán Ledesma Garza
 */
public class ViewPropertiesControls extends ViewComponent implements
        ActionListener,
        DocumentListener
{

    protected ImageRecord imageRecord;
    
    protected JPanel contentPanel_ = new JPanel();
    protected JPanel comboBoxesPanel_ = new JPanel();
    protected JPanel otherControlsPanel_ = new JPanel();
    
    protected JLabel categoryLabel_ = new JLabel("Category:");
    protected JLabel sizeLabel_ = new JLabel("Size:");
    protected JLabel privacyLevelLabel_ = new JLabel("Privacy Level:");
    protected JLabel formatLabel_ = new JLabel("Format:");
    protected JLabel descriptionLabel_ = new JLabel("Description:");
    
    protected JComboBox categoryComboBox_ = new JComboBox();
    protected JComboBox sizeComboBox_ = new JComboBox();
    protected JComboBox privacyLevelComboBox_ = new JComboBox();
    protected JComboBox formatComboBox_ = new JComboBox();
    protected JCheckBox favoriteCheckBox_ = new JCheckBox("Favorite");
    protected JTextArea descriptionTextArea_ = new JTextArea();
    
    public ViewPropertiesControls()
    {
        initializeControls();
        initializeComboBoxesPanel();
        initializeOtherControlsPanel();
        initializeContentPanel();
    }

    protected void initializeControls()
    {
        Dimension d;
     
        ///initialize descriptionTextArea_...
        d = new Dimension(300, 40);
        descriptionTextArea_.setMinimumSize(d);
        //descriptionTextArea_.setMaximumSize(d);
        descriptionTextArea_.setPreferredSize(d);
        descriptionTextArea_.setLineWrap(true);
        descriptionTextArea_.setWrapStyleWord(true);        
        
        //initialize favoriteCheckBox_...
        favoriteCheckBox_.setAlignmentX(0);
        
        //initialize descriptionLabel_...
        descriptionLabel_.setAlignmentX(0);
        
        ///initialize descriptionTextArea_....
        descriptionTextArea_.setAlignmentX(0);
        
        
        /*
        ///set fonts...
        Font myFont = new Font("Arial", Font.PLAIN, 10);
        
        categoryLabel_.setFont(myFont);
        categoryComboBox_.setFont(myFont);
         */
    }
    
    protected void initializeComboBoxesPanel()
    {
        ///create the combo
        GroupLayout layout = new GroupLayout(comboBoxesPanel_);
        
        comboBoxesPanel_.setLayout(layout);
        
        // Turn on automatically adding gaps between components
        layout.setAutoCreateGaps(true);

        // Turn on automatically creating gaps between components that touch
        // the edge of the container and the container.
        layout.setAutoCreateContainerGaps(true);

        // Create a sequential group for the horizontal axis.
        GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();

        // The sequential group in turn contains two parallel groups.
        // One parallel group contains the labels, the other the text fields.
        // Putting the labels in a parallel group along the horizontal axis
        // positions them at the same x location.
        //
        // Variable indentation is used to reinforce the level of grouping.
        hGroup.addGroup(layout.createParallelGroup().
                addComponent(categoryLabel_).
                addComponent(sizeLabel_).
                addComponent(privacyLevelLabel_).
                addComponent(formatLabel_)
                );
        hGroup.addGroup(layout.createParallelGroup().
                addComponent(categoryComboBox_).
                addComponent(sizeComboBox_).
                addComponent(privacyLevelComboBox_).
                addComponent(formatComboBox_)
                );
        layout.setHorizontalGroup(hGroup);

        // Create a sequential group for the vertical axis.
        GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();

        // The sequential group contains two parallel groups that align
        // the contents along the baseline. The first parallel group contains
        // the first label and text field, and the second parallel group contains
        // the second label and text field. By using a sequential group
        // the labels and text fields are positioned vertically after one another.
        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(categoryLabel_).
                addComponent(categoryComboBox_)
                );
        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(sizeLabel_).
                addComponent(sizeComboBox_)
                );
        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(privacyLevelLabel_).
                addComponent(privacyLevelComboBox_)
                );
        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(formatLabel_).
                addComponent(formatComboBox_)
                );
        layout.setVerticalGroup(vGroup);
    }
    
    protected void initializeOtherControlsPanel()
    {
        otherControlsPanel_.setAlignmentX(0.5f);
        
        BoxLayout layout = new BoxLayout(otherControlsPanel_, BoxLayout.Y_AXIS);
        
        otherControlsPanel_.setLayout(layout);
        
        otherControlsPanel_.add(favoriteCheckBox_);
        otherControlsPanel_.add(descriptionLabel_);
        otherControlsPanel_.add(descriptionTextArea_);
    }
    
    protected void initializeContentPanel()
    {   
        /*
        contentPanel_.setPreferredSize(new Dimension(300, 350));
        contentPanel_.setMinimumSize(new Dimension(200, 250));
        contentPanel_.setMaximumSize(new Dimension(400, 450));
        */
        
        BoxLayout layout = new BoxLayout(contentPanel_, BoxLayout.Y_AXIS);
        
        contentPanel_.setLayout(layout);
        
        contentPanel_.add(comboBoxesPanel_);
        contentPanel_.add(otherControlsPanel_);
        
        contentPanel_.repaint();
    }
    
    protected void listenToControls()
    {
        categoryComboBox_.addActionListener(this);
        sizeComboBox_.addActionListener(this);
        privacyLevelComboBox_.addActionListener(this);
        formatComboBox_.addActionListener(this);
        favoriteCheckBox_.addActionListener(this);
        descriptionTextArea_.getDocument().addDocumentListener(this);
    }
    
    protected void stopListeningToControls()
    {
        categoryComboBox_.removeActionListener(this);
        sizeComboBox_.removeActionListener(this);
        privacyLevelComboBox_.removeActionListener(this);
        formatComboBox_.removeActionListener(this);
        favoriteCheckBox_.removeActionListener(this);
        descriptionTextArea_.getDocument().removeDocumentListener(this);
    }
    
    @Override
    public void setInitialState(ModelState modelState)
    {
        ///update categories combobox items...
        {
            categoryComboBox_.removeAllItems();

            ArrayList<CategoryRecord> categoryRecords =
                    modelState.getCategoryRecords();

            Iterator<CategoryRecord> i = categoryRecords.iterator();
            CategoryRecord categoryRecord;
            while(i.hasNext())
            {
                categoryRecord = i.next();
                categoryComboBox_.addItem(categoryRecord);
            }
        }
        
        ///update size combobox items...
        {
            sizeComboBox_.removeAllItems();

            ArrayList<SizeRecord> sizeRecords =
                    modelState.getSizeRecords();

            Iterator<SizeRecord> i = sizeRecords.iterator();
            SizeRecord sizeRecord;
            while(i.hasNext())
            {
                sizeRecord = i.next();
                sizeComboBox_.addItem(sizeRecord);
            }
        }
        
        ///update privacy level combobox items...
        {
            privacyLevelComboBox_.removeAllItems();

            ArrayList<PrivacyLevelRecord> privacyLevelRecords =
                    modelState.getPrivacyLevelRecords();

            Iterator<PrivacyLevelRecord> i = privacyLevelRecords.iterator();
            PrivacyLevelRecord privacyLevelRecord;
            while(i.hasNext())
            {
                privacyLevelRecord = i.next();
                privacyLevelComboBox_.addItem(privacyLevelRecord);
            }
        }
        
        ///update format level combobox items...
        {
            formatComboBox_.removeAllItems();

            ArrayList<FormatRecord> formatRecords =
                    modelState.getFormatRecords();

            Iterator<FormatRecord> i = formatRecords.iterator();
            FormatRecord formatRecord;
            while(i.hasNext())
            {
                formatRecord = i.next();
                formatComboBox_.addItem(formatRecord);
            }
        }
        
        ///check whether there is an image selected...
        selectionChanged(modelState);
        
    }
    
    // <editor-fold desc="overriden & implemented operations...">
    @Override
    public void imageSetChanged(ModelState modelState)
    {
        ///do nothing...
    }
    
    @Override
    public void selectionChanged(ModelState modelState)
    {   
        stopListeningToControls();
        
        ///imageSetChanged selected options and control values...
        ImageRecord newImageRecord =
                modelState.getSelectedImageRecord();
        
        boolean controlsShouldEnable = newImageRecord != null;
        
        categoryComboBox_.setEnabled(controlsShouldEnable);
        sizeComboBox_.setEnabled(controlsShouldEnable);
        privacyLevelComboBox_.setEnabled(controlsShouldEnable);
        formatComboBox_.setEnabled(controlsShouldEnable);
        favoriteCheckBox_.setEnabled(controlsShouldEnable);
        if(newImageRecord == null || !newImageRecord.equals(imageRecord))
            descriptionTextArea_.setEnabled(controlsShouldEnable);
        
        ///if there is a selection...
        if(controlsShouldEnable)
        {
            /*
            categoryComboBox_.setSelectedIndex(imageRecord.getCategoryId());
            sizeComboBox_.setSelectedIndex(imageRecord.getSizeId());
            privacyLevelComboBox_.setSelectedIndex(imageRecord.getPrivacyLevelId());
            formatComboBox_.setSelectedIndex(imageRecord.getFormatId());
            */

            categoryComboBox_.setSelectedItem(newImageRecord.getCategory());
            sizeComboBox_.setSelectedItem(newImageRecord.getSize());
            privacyLevelComboBox_.setSelectedItem(newImageRecord.getPrivacyLevel());
            formatComboBox_.setSelectedItem(newImageRecord.getFormat());

            favoriteCheckBox_.setSelected(newImageRecord.isFavorite());
            if(newImageRecord == null || !newImageRecord.equals(imageRecord))
                descriptionTextArea_.setText(newImageRecord.getDescription());
        }
        else
        {
            descriptionTextArea_.setText("No image selected.");
        }
        
        imageRecord = newImageRecord;
        
        listenToControls();
    }

    @Override
    public void favoritesChanged(ModelState modelState)
    {
        ///do nothing...
    }

    @Override
    public void slideShowMode()
    {
        ///do nothing...
    }

    @Override
    public void gridMode()
    {
        ///do nothing...
    }

    @Override
    public Component getComponent()
    {
        return (Component)contentPanel_;
    }
    
    public void actionPerformed(ActionEvent e)
    {
        if(controller_ == null)
            return;
        
        Object source = e.getSource();
        
        if(source == categoryComboBox_)
        {
            imageRecord.setCategory(
                (CategoryRecord)categoryComboBox_.getSelectedItem());
            controller_.updateImageRecord(imageRecord);
        }
        else if(source == sizeComboBox_)
        {
            imageRecord.setSize(
                (SizeRecord)sizeComboBox_.getSelectedItem());
            controller_.updateImageRecord(imageRecord);
        }
        else if(source == privacyLevelComboBox_)
        {
            imageRecord.setPrivacyLevel(
                    (PrivacyLevelRecord)
                    privacyLevelComboBox_.getSelectedItem());
            controller_.updateImageRecord(imageRecord);
        }
        else if(source == formatComboBox_)
        {
            imageRecord.setFormat(
                (FormatRecord)formatComboBox_.getSelectedItem());
            controller_.updateImageRecord(imageRecord);
        }
        else if(source == favoriteCheckBox_)
        {
            imageRecord.setFavorite(favoriteCheckBox_.isSelected());
            controller_.updateImageRecord(imageRecord);
        }
    }

    public void insertUpdate(DocumentEvent e)
    {
        if(controller_ == null)
            return;
        
        Document source = e.getDocument();
        
        if(source == descriptionTextArea_.getDocument())
        {
            imageRecord.setDescription(
                    (String)descriptionTextArea_.getText());
            controller_.updateImageRecord(imageRecord);
        }
    }

    public void removeUpdate(DocumentEvent e)
    {
        insertUpdate(e);
    }

    public void changedUpdate(DocumentEvent e)
    {
        ///do nothing...
    }
    // </editor-fold>
}
